use std::sync::mpsc::{Sender, Receiver};
use specs::{System, Entities, ReadStorage, Component};
use specs::world::Index;
use crate::res::position_storage::Position;

struct Quad {
    origin_x: f32,
    origin_y: f32,
    range_x: f32,
    range_y: f32,
}

type Children = [QuadNode; 4];

enum QuadNode {
    Node(Quad, Children),
    Leaf(Quad, Vec<(Index, Position)>),
}

fn get_id(quad: Quad, position: Position) -> i32 {
    return (position.x > quad.origin_x) as i32 + 2*(position.y > quad.origin_y) as i32
}

fn convert_leaf_to_node(quad: Quad, entities: Vec<(Index, Position)>) -> QuadNode {
    let mut children: Children;
    for i in 0..4 {
        let xmod = i == 0 || i == 2 ? -1 : 1;
        let ymod = i == 0 || i == 1 ? -1 : 1;
        children[i] = Leaf(Quad {
            origin_x: quad.origin_x + (quad.range_x / 2)*xmod,
            origin_y: quad.origin_y + (quad.range_y / 2)*ymod,
            range_x: quad.range_x / 2,
            range_y: quad.ranbe_y / 2
        }, Vec::with_capacity(10));
    }

    for (entity, position) in entities {
        let id = get_id(quad, position);
        if let Leaf(quad, entities) = children[id] {
            entities.push((entity, position));
        }
    }

    return Node(quad, children);
}

fn add(QuadNode node, Position position, Index entity) -> QuadNode {
    if let Node(quad, children) = node {
        let id = get_id(quad, position);
        let child = children[id];

        children[id] = add(child, position, entity);

        return Node(quad, children);
    }

    if let Leaf(quad, entities) = node {
        if entities.size() >= 10 {
            let node = convert_leaf_to_node(quad, entities);
            return add(node, position, entity);
        }
    }
}

pub struct GetSystem;

impl<'a> System<'a> for GetSystem
{
    type SystemData = (
        ReadStorage<'a, Position>
    );

    fn run(&mut self, data: Self::SystemData) {
    }
}
